package jtech;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Stroke;
import java.util.LinkedList;

public class Drawer {
 
	private static Drawer instance = new Drawer();
	
	public static Drawer getInstance() {
		return instance;
	}
	
	public static final int ALIGN_LEFT   = -1;
	public static final int ALIGN_CENTER =  0;
	public static final int ALIGN_RIGHT  =  1;
	
    public static Font FONT_DEFAULT = new Font(Font.DIALOG, Font.PLAIN, 10);
    
	private static Stroke LINE_WIDTH_1 = new BasicStroke(1);
	private static Stroke LINE_WIDTH_2 = new BasicStroke(2);
	private static Stroke LINE_WIDTH_3 = new BasicStroke(3);
    
    private LinkedList<Graphics2D> stack = new LinkedList<Graphics2D>();
    
    public Graphics2D getGraphics2D() {
        return stack.getLast();
    }

    public void create(Graphics2D g2d) {
    	stack.addLast(g2d);
    }
    
    public void create() {
    	Graphics2D g2d = (Graphics2D) getGraphics2D().create();
    	stack.addLast(g2d);
    }
    
    public void dispose() {
    	Graphics2D g2d = stack.removeLast();
    	g2d.dispose();
    }
    
    public void disposeAll() {
    	while (!stack.isEmpty()) {
    		dispose();
    	}
    }
    
    public Drawer font(Font font) {
    	getGraphics2D().setFont(font);
    	return this;
    }
    
    public FontMetrics getFontMetrics() {
    	return getGraphics2D().getFontMetrics();
    }
    
    public int getLineHeight() {
    	return getFontMetrics().getHeight();
    }
    
    public Rectangle print(int align, float sx, float sy, String str, Object ... args) {

    	int height = getLineHeight();
        int minx = Integer.MAX_VALUE;
        int maxw = 0;
        
        String[] strs = String.format(str, args).split("\\n");

        for (int i = 0; i < strs.length; i++) {
        	int ix = (int) sx;
        	int iy = (int) (sy+height) + (height*i);
        	
        	int width = getFontMetrics().stringWidth(strs[i]);
        	
	        if (align == 0) {
	        	ix -= width / 2;
	        } else if (align == 1) {
	        	ix -= width;
	        }
        	
	        getGraphics2D().drawString(strs[i], ix, iy);
        	
	        minx = ix < minx ? ix : minx;
	        maxw = width > maxw ? width : maxw;
        }
        
        return new Rectangle(minx, (int) sy, maxw, strs.length*height);
    }
    
    public Rectangle printl(float sx, float sy, String str, Object ... args) {
    	return print(ALIGN_LEFT, sx, sy, str, args);
    }
    
    public Rectangle printc(float sx, float sy, String str, Object ... args) {
    	return print(ALIGN_CENTER, sx, sy, str, args);
    }
    
    public Rectangle printr(float sx, float sy, String str, Object ... args) {
    	return print(ALIGN_RIGHT, sx, sy, str, args);
    }
    
    public Drawer lineWidth1() {
    	getGraphics2D().setStroke(LINE_WIDTH_1);
    	return this;
    }
    
    public Drawer lineWidth2() {
    	getGraphics2D().setStroke(LINE_WIDTH_2);
    	return this;
    }
    
    public Drawer lineWidth3() {
    	getGraphics2D().setStroke(LINE_WIDTH_3);
    	return this;
    }
    
    public Drawer color(int r, int g, int b, int a) {
    	getGraphics2D().setColor(new Color(r, g, b, a));
        return this;
    }
    
    public Drawer color(Color c) {
    	getGraphics2D().setColor(c);
        return this;
    }
    
    public Drawer defaultFont() {
    	getGraphics2D().setFont(FONT_DEFAULT);
        return this;
    }
    
    public Drawer black() {
    	getGraphics2D().setColor(Color.BLACK);
        return this;
    }
    
    public Drawer white() {
    	getGraphics2D().setColor(Color.WHITE);
        return this;
    }
    
    public Drawer red() {
    	getGraphics2D().setColor(Color.RED);
        return this;
    }

    public Drawer blue() {
    	getGraphics2D().setColor(Color.BLUE);
        return this;
    }

    public Drawer gray() {
		getGraphics2D().setColor(Color.GRAY);
		return this;
	}
    
    public Drawer yellow() {
		getGraphics2D().setColor(Color.YELLOW);
		return this;
	}
    
    public Drawer circlef(float sx, float sy, float r) {
    	getGraphics2D().fillOval((int) (sx-r), (int) (sy-r), (int) (r*2), (int) (r*2));
    	return this;
    }
    
    public Drawer circle(float sx, float sy, float r) {
    	getGraphics2D().drawOval((int) (sx-r), (int) (sy-r), (int) (r*2), (int) (r*2));
        return this;
    }
    
    public Drawer ovalf(float sx, float sy, float w, float h) {
    	getGraphics2D().fillOval((int) (sx), (int) (sy), (int) (w), (int) (h));
    	return this;
    }
    
	public Drawer oval(float sx, float sy, float w, float h) {
    	getGraphics2D().drawOval((int) (sx), (int) (sy), (int) (w), (int) (h));
        return this;
    }
    
	public Drawer rectf(float x, float y, float w, float h) {
		getGraphics2D().fillRect((int) (x), (int) (y), (int) (w), (int) (h));
		return this;
	}

	public Drawer rect(float x, float y, float w, float h) {
		getGraphics2D().drawRect((int) (x), (int) (y), (int) (w), (int) (h));
		return this;
	}
    
	public Drawer squaref(float x, float y, float w) {
        rectf(x, y, w, w);
        return this;
    }
	
    public Drawer square(float x, float y, float w) {
        rect(x, y, w, w);
        return this;
    }
    
    public Drawer line(float x1, float y1, float x2, float y2) {
    	getGraphics2D().drawLine((int) (x1), (int) (y1), (int) (x2), (int) (y2));
        return this;
    }
    
    public Drawer draw(Image img, int dx, int dy, int sx, int sy, int w, int h) {
    	getGraphics2D().drawImage(img, dx, dy, dx+w, dy+h, sx, sy, sx+w, sy+h, null);
    	return this;
    }

	public Drawer clearRect(int w, int h) {
		getGraphics2D().clearRect(0, 0, w, h);
		return this;
	}

}
